/**
 * @file modbus_io_mgr.c
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2020-08-25
 * 
 * @copyright Copyright (c) 2020
 * 
 */

#include "modbus_io_mgr.h"

#include <stdio.h>
#include <stdlib.h>  // needed for sysconf(int name);
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <getopt.h>
#include <signal.h>
#include <sys/mman.h>  // Needed for mlockall()
#include <malloc.h>
#include <sys/time.h>      // needed for getrusage
#include <sys/resource.h>  // needed for getrusage
#include <sys/shm.h>
#include <limits.h>
#include <thread>
#include "3rd/libmodbus/modbus.h"
#include "zuc/nml_intf/zucpos.h"
#include "mb_slave.h"
#include "config.h"
#include "extio_mgr.h"
#include "hal/hal.h"
#include "log/zuclog.h"

#define MY_STACK_SIZE (4 * 1024 * 1024) /* 100 kB is enough for now. */
int quit_flag = 0;
static int hal_mod_id = 0;
static int extioKey = 200;
static int physicIOKey = 203;
ModbusIOShm_t* ModbusIOShmStruct = NULL;
PhysicIOShm_t* ModbusPhysicIOStruct = NULL;

void quit_signal(int signal)
{
    quit_flag = 1;  //tell the threads to quit (SIGTERM o SIGQUIT) (unloadusr mb2hal).
}

static void configure_malloc_behavior(void)
{
    if (mlockall(MCL_CURRENT | MCL_FUTURE))
        perror("mlockall failed:");

    mallopt(M_TRIM_THRESHOLD, -1);
    mallopt(M_MMAP_MAX, 0);
}

int extiomgr_init()
{
    int shm_id = shmget(extioKey, sizeof(ModbusIOShm_t), IPC_CREAT | 0666);
    if (shm_id < 0)
    {
        zucInnerDbg("get id error\n");
        return -1;
    }

    ModbusIOShmStruct = (ModbusIOShm_t*)shmat(shm_id, NULL, 0);  //

    if (ModbusIOShmStruct == NULL)
    {
        zucInnerDbg("get ptr error\n");
        return -2;
    }

    zucInnerDbg("[Modbus-IO_mgr]:>> get physic io share memory\n");
    shm_id = shmget(physicIOKey, sizeof(PhysicIOShm_t), IPC_CREAT | 0666);
    if (shm_id < 0)
    {
        zucInnerDbg("get id error\n");
        return -3;
    }

    ModbusPhysicIOStruct = (PhysicIOShm_t*)shmat(shm_id, NULL, 0);  //

    if (ModbusPhysicIOStruct == NULL)
    {
        zucInnerDbg("get ptr error\n");
        return -4;
    }

    return 0;
}
int extiomgr_thread_start()
{
    std::thread mbSlave(mb_slave_ServerThread);
    mbSlave.detach();
    sleep(1);  // modbus slave 先启动，扩展IO后启动，扩展IO可连接本机的slave
    std::thread mbMasterTcp(extio_tcp_mgr);
    mbMasterTcp.detach();
    std::thread mbMasterRtu(extio_rtu_mgr);
    mbMasterRtu.detach();
    return 0;
}